/******************************************************************************
   osg3DViewer: a 3D file viewer
   Copyright(C) 2015-2015  ronggenmiao@163.com

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software

 *******************************************************************************/
#pragma once

#include <QtCore/QTimer>
#include <osgViewer/CompositeViewer>
#include <osgGA/StateSetManipulator>
#include <osgQt/GraphicsWindowQt>
#include "publicDefined.h"

class xSceneModel;
class xSceneManger;
class QStandardItem;
class IEventCall;

/**
 * @brief 三维场景View，负责渲染显示三维场景
 */

class xSceneView : public QWidget, public osgViewer::CompositeViewer
{
    Q_OBJECT
public:
    xSceneView(QWidget *parent = NULL, IEventCall* pCallback = NULL);
    virtual ~xSceneView(void) {}

protected:
    /**
     * @brief GraphicsWindowQt之前改了底层代码，是个抽象类，对离屏渲染的一个接口重写
     */
    class CUserDefineGraphicsWindowQt : public osgQt::GraphicsWindowQt
    {
    public:
        CUserDefineGraphicsWindowQt(osg::GraphicsContext::Traits* traits) :
            GraphicsWindowQt(traits)
        {

        }

        virtual void SetOffScreen(bool isOffScreen) {}
    };
   
public:
    /**
     * @brief openScene  创建场景
     * @param fileName 场景文件名
     */
    void openScene(const std::string fileName);

    /**
     * @brief unloadAll  卸载所有场景
     */
    void unloadAll();

    /**
     * @brief home  回到初始角度
     */
    void home() const;

    /**
     * @brief setLightEnable  打开灯光
     */
    void setLightEnable() const;

    /**
     * @brief setTextureEnable  显示纹理
     */
    void setTextureEnable() const;

    /**
     * @brief frontView  前视
     */
    void frontView() const;

    /**
     * @brief rearView  后视
     */
    void rearView() const;

    /**
     * @brief leftView  左视
     */
    void leftView() const;

    /**
     * @brief rightView  右视
     */
    void rightView() const;

    /**
     * @brief lookUpView  仰视
     */
    void lookUpView() const;

    /**
     * @brief lookDownView  俯视
     */
    void lookDownView() const;

    /**
     * @brief vecOps 激活事件
     * @param vecOps 激活消息队列
     */
    void updateActivatedStatus(const std::vector<OperatingState> vecOps) const;

signals:
    /**
     * @brief sigAddFileToTree  信号，在树状列表中增加文件名
     */
    void sigAddFileToTree(const QString fileName);

    /**
     * @brief sigRemoveFileFromTree  信号，在树状列表中移除文件名
     */
    void sigRemoveFileFromTree();

public slots:
    /**
     * @brief slotUpdateModel  槽，更新模型
     */
    void slotUpdateModel();

    /**
     * @brief slotCheckNode  槽，check模型，改变显示或隐藏状态
     * @param item 被选中的项
     */
    void slotCheckNode(QStandardItem* item);

protected:
    /**
     * @brief addViewWidget  加入视窗渲染部件
     * @param gw osg和qt结合的图形窗口
     * @param scene 场景节点
     */
	QWidget* addViewWidget(osgQt::GraphicsWindowQt* gw, osg::Node* scene);

    /**
     * @brief createGraphicsWindow  创建图形窗口
     * @param x 窗口x坐标
     * @param y 窗口y坐标
     * @param w 窗口宽度
     * @param h 窗口高度
     * @param name 窗口名
     * @param windowDecoration 窗口装饰
     */
    osgQt::GraphicsWindowQt* createGraphicsWindow(int x, int y, int w, int h, const std::string& name = "",
                                                  bool windowDecoration = false);
    /**
     * @brief paintEvent  绘制事件
     * @param event 绘制事件
     */
    virtual void paintEvent(QPaintEvent *event);

    /**
     * @brief initManipulator  初始化操控器
     */
	void initManipulator();

    /**
     * @brief initEvent  初始化事件
     */
    void initEvent();

    /**
     * @brief initCamera  初始化相机
     * @param gw osg和qt结合的图形窗口
     */
    void initCamera(osgQt::GraphicsWindowQt *gw);

    /**
     * @brief initSceneGraph  初始化场景
     */
    void initSceneGraph();

    /**
     * @brief changeView  变换角度
     * @param rot 改变视角的旋转矩阵
     * @param rot 改变视角的平移矩阵
     */
    void changeView(const osg::Matrix rot, const osg::Matrix trans) const;

    /**
     * @brief calRotate  计算旋转矩阵
     * @param angle 计算旋转矩阵的角度
     * @param axis 计算旋转矩阵的转动轴
     */
    const osg::Matrix calRotate(const double angle, const osg::Vec3d axis) const;

    /**
     * @brief calRotate  计算平移矩阵
     * @param dxyz 偏移量
     * @param trans 返回的平移矩阵
     */
    bool calTrans(const osg::Vec3d dxyz, osg::Matrix &trans) const;

    /**
     * @brief pickTransPt  计算位移点, 也就是实际的eye的位置
     * @param dxyz 偏移量， 相对于物体的中心的便宜量，单位是物体的半径，(1, 0, 0)表示物体的x 方向一个物体半径的位置
     * @return 返回位移点坐标
     */
    const osg::Vec3d pickTransPt(const osg::Vec3d dxyz) const;

private:
    /**
     * @brief m_timer 计时器
     */
    QTimer m_timer;

    /**
     * @brief m_refreshPeriod 更新间隔
     */
    unsigned int m_refreshPeriod;

    /**
     * @brief m_pCamera 主相机
     */
	osg::ref_ptr<osg::Camera> m_pCamera;

    /**
     * @brief m_pView 主浏览窗口
     */
    osg::ref_ptr<osgViewer::View> m_pView;

    /**
     * @brief m_pModel 场景数据
     */
	xSceneModel *m_pModel;

    /**
     * @brief m_pManager 场景管理器
     */
    xSceneManger *m_pManager;

    /**
     * @brief pCallback 回调类
     */
    IEventCall *m_pCall;

};

